﻿// <copyright Autor="twitter.com/gotactile">
// Distributed under Microsoft Public License (Ms-PL)
// </copyright>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.Windows.Media.Animation;

namespace Con10uum
{
    public class FillCon10uumWindowEventArgs : EventArgs
    {
        public Con10uumWindow Control { get; set; }
        public object DataItem { get; set; }
    }

    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(Con10uumWindow))]
    public class Con10uum : ItemsControl
    {
        static Con10uum()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Con10uum), new FrameworkPropertyMetadata(typeof(Con10uum)));
        }

        private Con10uumGestureStateManager m_Con10uumMultitouchStateMachine;

        public Con10uum()
        {
            m_Con10uumMultitouchStateMachine = new Con10uumGestureStateManager(this);
        }

        public static readonly DependencyProperty OpenCloseAnimationDurationProperty = DependencyProperty.Register("OpenCloseAnimationDuration", typeof(Duration), typeof(Con10uum), new PropertyMetadata(new Duration(TimeSpan.FromMilliseconds(300))));

        public Duration OpenCloseAnimationDuration
        {
            get { return (Duration)GetValue(OpenCloseAnimationDurationProperty); }
            set { SetValue(OpenCloseAnimationDurationProperty, value); }
        }

        public static readonly DependencyProperty WindowMinWidthProperty = DependencyProperty.Register("WindowMinWidth", typeof(double), typeof(Con10uum), new PropertyMetadata(0.0));

        public double WindowMinWidth
        {
            get { return (double)GetValue(WindowMinWidthProperty); }
            set { SetValue(WindowMinWidthProperty, value); }
        }

        public static readonly DependencyProperty WindowMaxWidthProperty = DependencyProperty.Register("WindowMaxWidth", typeof(double), typeof(Con10uum), new PropertyMetadata(double.PositiveInfinity));

        public double WindowMaxWidth
        {
            get { return (double)GetValue(WindowMaxWidthProperty); }
            set { SetValue(WindowMaxWidthProperty, value); }
        }

        public static readonly DependencyProperty ResistanceProperty = DependencyProperty.Register("Resistance", typeof(double), typeof(Con10uum), new PropertyMetadata(0.0));

        public double Resistance
        {
            get { return (double)GetValue(ResistanceProperty); }
            set { SetValue(ResistanceProperty, value); }
        }

        public static readonly DependencyProperty MaxScrollVelocityProperty = DependencyProperty.Register("MaxScrollVelocity", typeof(double), typeof(Con10uum), new PropertyMetadata(double.PositiveInfinity));

        public double MaxScrollVelocity
        {
            get { return (double)GetValue(MaxScrollVelocityProperty); }
            set { SetValue(MaxScrollVelocityProperty, value); }
        }

        public event EventHandler<FillCon10uumWindowEventArgs> FillContainerRequested;

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            if (FillContainerRequested != null)
            {
                FillContainerRequested(this, new FillCon10uumWindowEventArgs { Control = element as Con10uumWindow, DataItem = item });

            }
            else
            {
                base.PrepareContainerForItemOverride(element, item);
            }

            Con10uumWindow e = element as Con10uumWindow;
            if (e != null)
            {
                e.AddHandler(Con10uumWindow.ClosedEvent, new RoutedEventHandler(Con10uumWindow_Closed));
                e.AddHandler(Con10uumWindow.TapEvent, new RoutedEventHandler(Con10uumWindow_Tap));
            }
        }

        void Con10uumWindow_Tap(object sender, RoutedEventArgs e)
        {
            if (this.m_Con10uumMultitouchStateMachine.Con10uumCurrentState is ZoomedState)
            {
                ZoomedState zs = (ZoomedState)this.m_Con10uumMultitouchStateMachine.Con10uumCurrentState;
                zs.ReportCon10uumWindow_Tap(sender, e);
            }
        }

        void Con10uumWindow_Closed(object sender, RoutedEventArgs e)
        {
            this.Items.Remove(sender);
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new Con10uumWindow();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is Con10uumWindow;
        }

        /// <summary>
        /// Template of the header part of each item
        /// </summary>
        public DataTemplate ItemHeaderTemplate
        {
            get { return (DataTemplate)GetValue(ItemHeaderTemplateProperty); }
            set { SetValue(ItemHeaderTemplateProperty, value); }
        }

        public static readonly DependencyProperty ItemHeaderTemplateProperty =
            DependencyProperty.RegisterAttached("ItemHeaderTemplate",
                typeof(DataTemplate), typeof(Con10uum),
                new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.Inherits,
                    OnItemHeaderTemplateChanged));

        private static void OnItemHeaderTemplateChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs args)
        {
            var lst = obj as Con10uum;
            if (lst != null)
            {
                lst.OnItemHeaderTemplateChanged(args.OldValue as DataTemplate,
                    args.NewValue as DataTemplate);
            }
        }
        protected virtual void OnItemHeaderTemplateChanged(DataTemplate oldTemplate,
            DataTemplate newTemplate)
        {

        }


        /// <summary>
        /// TemplateSelector for the header part of each item
        /// </summary>
        public DataTemplateSelector ItemHeaderTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(ItemHeaderTemplateSelectorProperty); }
            set { SetValue(ItemHeaderTemplateSelectorProperty, value); }
        }

        public static readonly DependencyProperty ItemHeaderTemplateSelectorProperty =
            DependencyProperty.RegisterAttached("ItemHeaderTemplateSelector",
                typeof(DataTemplateSelector), typeof(Con10uum),
                new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.Inherits,
                    OnItemHeaderTemplateSelectorChanged));

        private static void OnItemHeaderTemplateSelectorChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs args)
        {
            var lst = obj as Con10uum;
            if (lst != null)
            {
                lst.OnItemHeaderTemplateSelectorChanged(args.OldValue as DataTemplateSelector,
                    args.NewValue as DataTemplateSelector);
            }
        }
        protected virtual void OnItemHeaderTemplateSelectorChanged(DataTemplateSelector oldTemplateSelector,
            DataTemplateSelector newTemplateSelector)
        {

        }


        /// <summary>
        /// Template of the content of each item
        /// </summary>
        public DataTemplate ItemContentTemplate
        {
            get { return (DataTemplate)GetValue(ItemContentTemplateProperty); }
            set { SetValue(ItemContentTemplateProperty, value); }
        }

        public static readonly DependencyProperty ItemContentTemplateProperty =
            DependencyProperty.RegisterAttached("ItemContentTemplate",
                typeof(DataTemplate), typeof(Con10uum),
                new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.Inherits,
                    OnItemContentTemplateChanged));

        private static void OnItemContentTemplateChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs args)
        {
            var lst = obj as Con10uum;
            if (lst != null)
            {
                lst.OnItemContentTemplateChanged(args.OldValue as DataTemplate,
                    args.NewValue as DataTemplate);
            }
        }
        protected virtual void OnItemContentTemplateChanged(DataTemplate oldTemplate,
            DataTemplate newTemplate)
        {

        }


        /// <summary>
        /// TemplateSelector for the content of each item
        /// </summary>
        public DataTemplateSelector ItemContentTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(ItemContentTemplateSelectorProperty); }
            set { SetValue(ItemContentTemplateSelectorProperty, value); }
        }

        public static readonly DependencyProperty ItemContentTemplateSelectorProperty =
            DependencyProperty.RegisterAttached("ItemContentTemplateSelector",
                typeof(DataTemplateSelector), typeof(Con10uum),
                new FrameworkPropertyMetadata(null,
                    FrameworkPropertyMetadataOptions.Inherits,
                    OnItemContentTemplateSelectorChanged));
        private static void OnItemContentTemplateSelectorChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs args)
        {
            var lst = obj as Con10uum;
            if (lst != null)
            {
                lst.OnItemContentTemplateSelectorChanged(args.OldValue as DataTemplateSelector,
                    args.NewValue as DataTemplateSelector);
            }
        }
        protected virtual void OnItemContentTemplateSelectorChanged(DataTemplateSelector oldTemplateSelector,
            DataTemplateSelector newTemplateSelector)
        {

        }
    }
}
